#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

#include "URAT.h"

#define MAX_LINE_LENGTH 1024
DWORD WINAPI SerialReadThread(LPVOID lpParam);
char line[MAX_LINE_LENGTH];
uint8_t checksum;
FILE *file;


uint8_t targetLineCount = 0;

// Function to convert two hex characters to a byte
uint8_t hexCharToByte(char hi, char lo) {
	uint8_t value = 0;
	if (hi >= '0' && hi <= '9') value += (hi - '0') << 4;
	else if (hi >= 'A' && hi <= 'F') value += (hi - 'A' + 10) << 4;
	else if (hi >= 'a' && hi <= 'f') value += (hi - 'a' + 10) << 4;

	if (lo >= '0' && lo <= '9') value += (lo - '0');
	else if (lo >= 'A' && lo <= 'F') value += (lo - 'A' + 10);
	else if (lo >= 'a' && lo <= 'f') value += (lo - 'a' + 10);

	return value;
}

// Parse a single line of Intel HEX and print its components
void parseLine(const char* line) {
	static int index = 1;
	static long int Base_Address = 0X08000000;

	if (line[0] != ':') {
		fprintf(stderr, "Invalid record (missing ':'): %s", line);
		return;
	}

	size_t len = strlen(line);
	if (len < 11) {
		fprintf(stderr, "Line too short to be valid: %s", line);
		return;
	}

	// Byte count
	uint8_t byteCount = hexCharToByte(line[1], line[2]);
	// Address
	uint16_t address = (hexCharToByte(line[3], line[4]) << 8) | hexCharToByte(line[5], line[6]);
	// Record type
	uint8_t recordType = hexCharToByte(line[7], line[8]);

	// Data
	uint8_t data[256];
	for (int i = 0; i < byteCount; i++) {
		int idx = 9 + i * 2;
		data[i] = hexCharToByte(line[idx], line[idx + 1]);
	}

	// Checksum
	uint8_t checksum = hexCharToByte(line[9 + byteCount * 2], line[9 + byteCount * 2 + 1]);

	// Verify checksum
	uint32_t sum = byteCount + (address >> 8) + (address & 0xFF) + recordType;
	for (int i = 0; i < byteCount; i++) sum += data[i];
	sum = (sum + checksum) & 0xFF;
	if (recordType == 0) {
		//printf("索引:%03d,字节数=%02u, 地址=0x%04X, 类型=%u, 校验和=0x%02X (%s)",
		printf("索引:%03d,字节数=%02u, 地址=0x%04X, 类型=%u, 校验和=0x%02X (%s)",
		index++, byteCount, Base_Address | address, recordType, checksum, (sum == 0 ? "OK" : "ALL"));

		if (byteCount > 0) {
			printf("  数据体: ");
			for (int i = 0; i < byteCount; i++) {
				printf("%02X ", data[i]);
			}
			printf("\n");
		}
		printf("\n");
	}
}

int main(void) {
	// 在这里指定要解析的 Intel HEX 文件路径
	//const char *filePath = "BootLoader.hex";
	const char *filePath = "App.hex";

	file = fopen(filePath, "r");//打开文件-只读
	if (!file) {
		perror("Failed to open file");
		return EXIT_FAILURE;
	}

	//打开串口
	if (Open_URAT("COM3")) {
		URAT_Config();//配置串口
	}

	fgets(line, sizeof(line), file);
	if (line[0] != '\n' || line[0] != '\r') { // 跳过空行
		uint8_t byteCount = hexCharToByte(line[1], line[2]);
		checksum = hexCharToByte(line[9 + byteCount * 2], line[9 + byteCount * 2 + 1]);
		//printf("校验和=0x%02X\n", checksum);
		sendData(line);
	}
	
	/*
		while(fgets(line, sizeof(line), file)){
		if (line[0] != '\n' || line[0] != '\r') { // 跳过空行
		parseLine(line);
		}		
		}	
		
	*/	
	
	// 启动接收线程
	HANDLE hThread = CreateThread(NULL, 0, SerialReadThread, NULL, 0, NULL);
	if (hThread == NULL) {
		printf("线程创建失败\n");
		CloseHandle(hSerial);
		return 1;
	}

	// 主线程等待接收线程
	WaitForSingleObject(hThread, INFINITE);
	fclose(file);//关闭文件
	return EXIT_SUCCESS;
}


// 接收线程函数
DWORD WINAPI SerialReadThread(LPVOID lpParam) {
	char recvBuf[4];
	DWORD bytesRead;

	static int k = 0;


	while (1) {
		if (ReadFile(hSerial, recvBuf, sizeof(recvBuf) - 1, &bytesRead, NULL)) {
			if (bytesRead > 0) {
				recvBuf[bytesRead] = '\0';  // 字符串结束
				printf("接收数据：%s\n", recvBuf);
				char str[4];
				sprintf(str, "%02X", checksum);
				if (strcmp(recvBuf, str) == 0) {
					if (fgets(line, sizeof(line), file)) {
						if (line[0] == '\n' || line[0] == '\r') { // 跳过空行

						} else {
							uint8_t byteCount = hexCharToByte(line[1], line[2]);
							checksum = hexCharToByte(line[9 + byteCount * 2], line[9 + byteCount * 2 + 1]);
							//printf("校验和=0x%02X\n",checksum);
							//lineCount1++;
							//printf("当前行：%d\n",lineCount-lineCount1);
							sendData(line);
						}
					} else {
						printf("下载完成!");
					}
				} else {
					k++;
					if (k >= 3 ) {
						printf("新发送3次,后仍然失败!\n", k);
					} else {
						printf("欲比对：%s!=%s\n", recvBuf, str);
						printf("校验失败从新发送%d次\n", k);
						sendData(line);
					}

				}
			}
		} else {
			printf("读取失败\n");
			break;
		}
	}
	return 0;
}
